// MIMEMail.cpp: implementation of the CMIMEMail class.
//
//////////////////////////////////////////////////////////////////////

#include "MIMEMail.h"
#include "Sockets/Utility.h"
#include "Sockets/Base64.h"
#include "MyParse.h"
#include  <io.h>
#include <iostream>
#include <fstream>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMIMEMail::CMIMEMail()
:m_strBoundary("9a78107bce7145a6882a550cde6c2020")
,m_strCharset("gb2312")
{

}

CMIMEMail::~CMIMEMail()
{
}

void CMIMEMail::SetBoundary(const std::string &boundary)
{
	if (!boundary.empty())
		m_strBoundary = boundary;
}

std::string CMIMEMail::GetBoundary()
{
	return m_strBoundary;
}

void CMIMEMail::SetAttach(const std::string &attach)
{
	MyParse pa(attach, ",");
	
	for (std::string str(pa.getsplit()); 
	!str.empty(); str = pa.getsplit())
	{
		AddAttach(str);
	}
}

void CMIMEMail::AddAttach(const std::string& path, 
						  const std::string& name/* = ""*/,
						  const std::string& type/* = ""*/, 
						  const std::string& description/* = ""*/)
{
	Attachment attach;
	attach.Path = path;
	attach.Name = name;
	attach.ContentType = type;
	attach.Description = description;

	if(name.empty())
	{
		int idx = path.rfind('\\');
		if(idx<0)
			attach.Name = path;
		else
			attach.Name = path.substr(idx+1);
	}

	if(type.empty())
		attach.ContentType = "application/octet-stream";

	m_vAttachList.push_back(attach);
}

void CMIMEMail::GenerateHeader()
{
	m_strHeader = "";

	// From
	m_strHeader += "From: \"";
	
	if(m_strCharset.empty())
		m_strHeader += m_From.alias;
	else
		m_strHeader += "=?" + m_strCharset + "?B?" 
					+ Utility::base64(m_From.alias)
					+ "?=";
	m_strHeader += "\" <" + m_From.addr + ">\r\n";

	// Subject
	m_strHeader += "Subject: ";
	
	if(m_strCharset.empty())
		m_strHeader += m_strSubject;
	else
		m_strHeader += "=?" + m_strCharset + "?B?"
					+ Utility::base64(m_strSubject)
					+ "?=";
	m_strHeader += "\r\n";
	
	// To, Cc, Bcc
	std::string to, cc, bcc;
	for (int i=0; i < m_vToList.size(); i++)
	{
		switch (m_vToList[i].type)
		{
		case TO:
			to += "\"" + m_strCharset.empty()?m_vToList[i].alias:
				("=?" + m_strCharset + "?B?" + Utility::base64(m_vToList[i].alias)
				+"?=");
			to += "\" <" + m_vToList[i].addr + ">, ";
			break;
		case CC:
			cc += "\"" + m_strCharset.empty()?m_vToList[i].alias:
				("=?" + m_strCharset + "?B?" + Utility::base64(m_vToList[i].alias)
				+"?=");
			cc += "\" <" + m_vToList[i].addr + ">, ";
			break;
		case BCC:
			bcc += "\"" + m_strCharset.empty()?m_vToList[i].alias:
				("=?" + m_strCharset + "?B?" + Utility::base64(m_vToList[i].alias)
				+"?=");
			bcc += "\" <" + m_vToList[i].addr + ">, ";
			break;
		default:
			break;
		}
	}
	
	m_strHeader += "To: " + to + "\r\n";
	if(!cc.empty())
		m_strHeader += "Cc: " + cc + "\r\n";
	//	if(!bcc.IsEmpty())
	//		m_strHeader += "Bcc: " + bcc + "\r\n";


	m_strHeader += "MIME-Version: 1.0\r\n"
		"Content-Type: multipart/mixed;\r\n"
		" boundary=\"" + m_strBoundary + "\";\r\n"
		"Content-Transfer-Encoding: 7bit\r\n"
		"\r\n"
		"This is a MIME Encoded Message.\r\n"
		"\r\n";
}

std::string CMIMEMail::GetContent()
{
	std::string header("--" + m_strBoundary + "\r\n"
		+ "Content-Type: text/plain; ");
	if (!m_strCharset.empty())
		header += "charset=" + m_strCharset;
	header +=  "\r\nContent-Transfer-Encoding: base64\r\n" ;

	return header 
		+ "\r\n" 
		+ Utility::base64(m_strContent)
		+ "\r\n\r\n";
}

void CMIMEMail::SetCharset(const std::string &charset)
{
	m_strCharset = charset;
}

std::string CMIMEMail::GetCharset()
{
	return m_strCharset;
}

bool CMIMEMail::GetFirstAttach(std::string & data)
{
	m_nCurAttach = 0;
	return GetCurAttach(data);
}

bool CMIMEMail::GetCurAttach(std::string & data)
{
	if (m_nCurAttach < 0 || m_nCurAttach >= m_vAttachList.size())
		return false;
	
	data.empty();

	Attachment attach = m_vAttachList[m_nCurAttach];

	if(access(attach.Path.c_str(), 0))
		return true;

	std::string header("--" + m_strBoundary + "\r\n"
		+ "Content-Type: " + attach.ContentType 
		+ "; name=\"" + attach.Name + "\"\r\n"
		+ "Content-Transfer-Encoding: base64\r\n"
		+ "Content-Description: " + attach.Description + "\r\n\r\n");

	data += header;

	// read file
	std::string filedata;

// 	std::ifstream file(attach.Path, std::ios_base::in | std::ios_base::binary);
// 	
// 	if ( !file )
// 		return true;
// 	
// 	std::istreambuf_iterator<char> dataBegin(file);
// 	
// 	std::istreambuf_iterator<char> dataEnd;
// 
// 	std::copy(dataBegin, dataEnd, str_back_inserter(filedata));
// 	file.close();

	FILE * file = fopen(attach.Path.c_str(), "rb");
	if(NULL == file)
		return true;

	Base64 b6;
	b6.encode(file, filedata);
	fclose(file);
	file = NULL;

	data += filedata + "\r\n\r\n";
	return true;
}

bool CMIMEMail::GetNextAttach(std::string & data)
{
	if(m_nCurAttach < m_vAttachList.size())
		m_nCurAttach ++;

	return GetCurAttach(data);
}

void CMIMEMail::GetData(std::string& data)
{
	data = GetHeader() + "\r\n\r\n";
	data += GetContent() + "\r\n\r\n";

	std::string attach;
	for (bool ret = GetFirstAttach(attach); ret; 
		ret = GetNextAttach(attach))
	{
		data += attach;
	}

	data += "--" + m_strBoundary + "--\r\n";
}